iT邦幫忙

2026 iThome 鐵人賽

DAY 2
0

前言

在上一篇文章中,我們認識了JSON的基本語法,包括Object、Array、String、Number及Boolean。

但是,FHIR不只要求資料符合JSON語法,還會進一步規定每個欄位應使用哪一種FHIR資料型別。

例如,以下資料在JSON語法上沒有問題:

{
  "birthDate": "我不記得了"
}

birthDate的Value是一個合法的JSON String,但FHIR規定Patient的birthDate必須符合date資料型別,所以「我不記得了」並不是有效的FHIR出生日期。

這表示:

JSON資料型別負責基本語法,FHIR資料型別則進一步規定醫療資料應該如何表達。

今天就來認識FHIR中經常使用的基本型別及複合型別。


為什麼FHIR需要自己的資料型別?

如果所有資料都只使用一般文字表示,系統很難正確理解內容。

例如:

{
  "result": "60"
}

這個60代表什麼?

它可能是:

  • 體重60公斤
  • 心跳每分鐘60次
  • 血糖60 mg/dL
  • 住院60天
  • 檢驗結果的文字編號

如果只交換一個數字,接收方不知道它的測量項目、單位及意義。

FHIR因此定義了不同資料型別,用來表示:

  • 日期
  • 時間
  • 姓名
  • 地址
  • 聯絡方式
  • 識別碼
  • 標準代碼
  • 數值與單位
  • 時間區間
  • Resource之間的連結

如此一來,系統不只收到Value,也能理解這項Value應該如何被處理。


FHIR資料型別的兩大類

為了方便初學,可以先將常見FHIR資料型別分成兩類:

1. 基本型別

基本型別通常只有一個值,例如:

  • boolean
  • integer
  • decimal
  • string
  • code
  • uri
  • date
  • dateTime

2. 複合型別

複合型別由多個欄位組成,例如:

  • Identifier
  • HumanName
  • Address
  • ContactPoint
  • Coding
  • CodeableConcept
  • Quantity
  • Period
  • Reference

要注意FHIR官方命名的大小寫:

  • 基本型別通常使用小寫開頭,例如stringdateTime
  • 複合型別通常使用大寫開頭,例如HumanNameAddress

接下來先從基本型別開始。


一、常見基本型別

boolean:是或否

boolean只有兩個值:

true
false

例如Patient的active欄位:

{
  "resourceType": "Patient",
  "active": true
}

表示這筆Patient紀錄目前有效。

在JSON中,boolean不能加上雙引號,也要使用小寫。

正確:

"active": true

錯誤:

"active": "true"

錯誤:

"active": True

第一個錯誤把Boolean寫成String,第二個錯誤則使用了JSON不接受的大寫形式。


integer:整數

integer用來表示沒有小數點的整數。

例如:

"rank": 1

正確的integer不需要雙引號:

1

如果寫成:

"1"

它就會變成String。

FHIR不同欄位可能對整數範圍有進一步限制。例如,有些欄位只能使用正整數,會使用positiveInt;有些欄位允許0但不允許負數,可能使用unsignedInt。


decimal:小數

decimal可以表示整數或包含小數點的數值,例如:

37.2
60

在FHIR中,decimal經常出現在測量數值中,例如體溫、身高及體重。

不過,醫療測量通常不能只放一個decimal,還需要一起記錄測量單位,因此經常會放在Quantity複合型別中。

例如:

"valueQuantity": {
  "value": 37.2,
  "unit": "°C"
}

string:一般文字

string用來表示一般文字,JSON中需要使用雙引號。

例如:

"display": "王小明"
"text": "病人主訴頭暈"

string可以用來提供人類閱讀的內容,但如果資料需要讓電腦進一步分類或比對,通常不能只依靠自由文字。

例如,疾病名稱如果只寫成:

"text": "高血壓"

其他系統可能不知道它對應哪一個標準診斷代碼。

這時就可能需要使用Coding或CodeableConcept。


code:受限制的代碼文字

code在JSON中看起來也是字串:

"gender": "male"

但它和一般string不同。

string通常可以放入較自由的文字;code則通常必須從特定代碼集合中選擇。

例如,Patient的gender在FHIR R4中可以使用:

  • male
  • female
  • other
  • unknown

不能自行寫成:

"gender": "男"

也不能自行縮寫成:

"gender": "M"

除非規範允許,否則系統應使用FHIR定義的代碼。


uri:資源識別位置

uri用來表示統一資源識別碼。

例如Identifier中的system

"system": "https://hospital.example.org/mrn"

這個URI不是用來表示病歷號本身,而是識別「病歷號屬於哪一套編號系統」。

FHIR中經常使用URI識別:

  • 識別碼系統
  • CodeSystem
  • ValueSet
  • Profile
  • Extension定義
  • 其他標準資源

URI看起來可能像一般網址,但它的主要用途是提供全球唯一或清楚的識別,不代表每一個URI都一定能用瀏覽器開啟。


date:日期

date用來表示日期。

完整格式通常是:

YYYY-MM-DD

例如:

"birthDate": "2000-01-01"

FHIR date也可以只記錄已知的部分。

只知道年份:

"birthDate": "2000"

只知道年份及月份:

"birthDate": "2000-01"

知道完整日期:

"birthDate": "2000-01-01"

如果來源資料只知道病人出生於2000年,就不應自行補成2000年1月1日,因為這會製造原本不存在的資料。


dateTime:日期加時間

dateTime可以同時記錄日期及時間。

例如:

"effectiveDateTime": "2026-09-03T09:30:00+08:00"

可以拆成:

部分 意義
2026-09-03 日期
T 分隔日期與時間
09:30:00 時、分、秒
+08:00 時區

臺灣時間通常使用UTC+8,所以範例中使用+08:00

時間資料如果缺少時區,跨地區或跨系統交換時可能產生誤解。

dateTime適合表示:

  • 量測時間
  • 看診開始時間
  • 檢體採集時間
  • 醫令開立時間
  • Resource中的臨床事件時間

date與dateTime的差異

資料型別 內容 範例
date 日期 2000-01-01
dateTime 日期及時間 2026-09-03T09:30:00+08:00

病人的出生日期通常只需要date:

"birthDate": "2000-01-01"

檢驗或生命徵象的量測時間則可能需要dateTime:

"effectiveDateTime": "2026-09-03T09:30:00+08:00"

雖然date與dateTime在JSON中都以String呈現,但FHIR會針對內容格式做更進一步的限制。


二、常見複合型別

Identifier:識別碼

Identifier用來表示醫療或行政流程中的識別資料,例如:

  • 病歷號
  • 醫令編號
  • 檢體編號
  • 員工編號
  • 醫療機構代碼

範例:

"identifier": [
  {
    "use": "usual",
    "system": "https://hospital.example.org/mrn",
    "value": "MRN0001"
  }
]

Identifier常見欄位包括:

欄位 用途
use 識別碼用途
type 識別碼類型
system 識別碼所屬系統
value 實際識別碼
period 識別碼有效期間
assigner 核發識別碼的機構

只看value可能不夠。

假設兩家醫院都有病歷號MRN0001,必須搭配不同的system,才能知道它們分別屬於哪家醫院。


HumanName:人名

HumanName用來表示人的姓名。

範例:

"name": [
  {
    "use": "official",
    "text": "王小明",
    "family": "王",
    "given": [
      "小明"
    ]
  }
]

常見欄位包括:

欄位 用途
use 姓名用途
text 適合直接顯示的完整姓名
family 姓氏或家族名稱
given 名字
prefix 姓名前綴
suffix 姓名後綴
period 姓名使用期間

name通常可以出現多次,因此能同時記錄正式姓名、舊名或暱稱。

FHIR將姓名設計成複合型別,是因為不同國家及文化的姓名結構並不相同。


Address:地址

Address用來表示郵寄地址或實體地址。

範例:

"address": [
  {
    "use": "home",
    "type": "both",
    "text": "桃園市中壢區範例路100號",
    "city": "中壢區",
    "district": "桃園市",
    "country": "TW"
  }
]

常見欄位包括:

欄位 用途
use 住家、工作或舊地址等用途
type 郵寄地址、實體地址或兩者皆是
text 完整顯示文字
line 街道及門牌等地址內容
city 城市或地區
district 行政區域
state 州或其他行政區
postalCode 郵遞區號
country 國家
period 地址有效期間

由於各國地址格式不同,實際在臺灣使用時仍應參考TW Core IG對地址的規定。


ContactPoint:聯絡方式

ContactPoint用來表示:

  • 電話
  • 電子郵件
  • 傳真
  • 其他通訊方式

範例:

"telecom": [
  {
    "system": "phone",
    "value": "0900-000-001",
    "use": "mobile",
    "rank": 1
  }
]

常見欄位包括:

欄位 用途
system 電話、電子郵件或傳真等類型
value 實際聯絡內容
use 住家、工作或行動電話等用途
rank 優先順序
period 有效期間

如果病人有多種聯絡方式,可以在telecom Array中放入多個ContactPoint。


Coding:標準代碼

Coding用來表示一個來自特定CodeSystem的代碼。

範例:

{
  "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus",
  "code": "S",
  "display": "Never Married"
}

常見欄位包括:

欄位 用途
system 代碼系統的識別URI
version 代碼系統版本
code 實際代碼
display 方便人類閱讀的名稱
userSelected 是否由使用者直接選擇

其中,電腦主要利用systemcode辨認概念。

只看到:

"code": "S"

並不能確定它代表什麼,因為不同CodeSystem都可能使用代碼S

加入system後,接收方才能知道應該到哪一套代碼系統解讀。


CodeableConcept:可使用代碼表達的概念

CodeableConcept可以包含一個或多個Coding,也可以加入人類可閱讀的text

範例:

"maritalStatus": {
  "coding": [
    {
      "system": "http://terminology.hl7.org/CodeSystem/v3-MaritalStatus",
      "code": "S",
      "display": "Never Married"
    }
  ],
  "text": "未婚"
}

可以把Coding和CodeableConcept的差異簡化成:

  • Coding:一組特定代碼系統中的代碼。
  • CodeableConcept:一個醫療概念,可以包含一組或多組Coding及顯示文字。

為什麼需要一個以上的Coding?

同一個醫療概念可能同時對應:

  • 國際標準代碼
  • 國家標準代碼
  • 醫院院內代碼

CodeableConcept可以將這些對應同時放在同一個概念中。


Quantity:數值與單位

Quantity用來表達具有測量單位的數值。

例如體重:

"valueQuantity": {
  "value": 60.2,
  "unit": "kg",
  "system": "http://unitsofmeasure.org",
  "code": "kg"
}

常見欄位包括:

欄位 用途
value 數值
comparator 大於、小於等比較符號
unit 顯示給人看的單位
system 單位代碼系統
code 系統處理的單位代碼

unit與code有什麼不同?

"unit": "kg"

主要提供人類閱讀。

"code": "kg"

則是搭配指定的system供電腦進行標準化處理。

FHIR常使用UCUM表示測量單位,其URI為:

http://unitsofmeasure.org

只寫:

"value": 60.2

無法知道是公斤、磅還是其他單位,因此測量資料通常要同時提供數值與單位。


Period:一段時間

Period用來表示具有開始及結束的時間區間。

例如一次住院期間:

"period": {
  "start": "2026-09-01T08:00:00+08:00",
  "end": "2026-09-03T15:00:00+08:00"
}

其中:

  • start:開始時間
  • end:結束時間

Period可以應用在:

  • 住院期間
  • 姓名使用期間
  • 地址有效期間
  • 識別碼有效期間
  • 醫療人員參與照護的時間

如果事件尚未結束,Period也可能只有start,沒有end


Reference:連結其他Resource

Reference用來建立Resource之間的關係。

例如,一筆Observation要指出資料屬於哪一位病人:

"subject": {
  "reference": "Patient/patient-example",
  "display": "王小明"
}

常見欄位包括:

欄位 用途
reference 指向另一筆Resource
type 目標Resource類型
identifier 使用業務識別碼指出對象
display 提供人類閱讀的文字

在這個範例中:

"reference": "Patient/patient-example"

是實際指向Patient Resource的連結。

"display": "王小明"

只是方便人類閱讀,不能只靠姓名建立資料關係,因為不同病人可能擁有相同姓名。

Reference會在Day 11進一步介紹。


相同的JSON String,可能是不同FHIR型別

下面三個值在JSON中都是String:

"王小明"
"2000-01-01"
"male"

但是放到FHIR欄位後,可能代表不同FHIR資料型別:

FHIR欄位 JSON呈現 FHIR資料型別
text "王小明" string
birthDate "2000-01-01" date
gender "male" code

所以只看JSON外觀還不夠,仍然需要查閱FHIR規範,確認欄位要求的FHIR資料型別。


如何在FHIR官方網站查看資料型別?

開啟FHIR Resource的官方頁面後,可以看到欄位結構表。

以Patient為例,可能看到:

Patient.identifier     Identifier
Patient.name           HumanName
Patient.telecom        ContactPoint
Patient.gender         code
Patient.birthDate      date
Patient.address        Address

左邊是欄位名稱,右邊是資料型別。

有些欄位旁邊還會出現:

0..1

或:

0..*

這不是資料型別,而是Cardinality,也就是欄位允許出現的次數。

例如:

  • 0..1:可以不出現,最多出現一次。
  • 0..*:可以不出現,也可以出現很多次。
  • 1..1:必須出現一次。
  • 1..*:至少出現一次,也可以出現很多次。

Cardinality和資料型別是不同概念:

  • 資料型別回答「這個欄位要放什麼資料?」
  • Cardinality回答「這個欄位可以出現幾次?」

常見資料型別整理

資料型別 主要用途 範例
boolean 是或否 true
integer 整數 1
decimal 數值 37.2
string 一般文字 "王小明"
code 規範限制的代碼 "male"
uri 識別系統或規範位置 "https://example.org"
date 日期 "2000-01-01"
dateTime 日期及時間 "2026-09-03T09:30:00+08:00"
Identifier 病歷號等識別資料 system+value
HumanName 人名 family+given
Address 地址 text+city+country
ContactPoint 聯絡方式 system+value
Coding 一組標準代碼 system+code+display
CodeableConcept 可由多組代碼表達的概念 coding+text
Quantity 數值與單位 value+unit+code
Period 時間區間 start+end
Reference 連結另一筆Resource reference+display

今日練習

請觀察以下Observation片段:

{
  "resourceType": "Observation",
  "status": "final",
  "subject": {
    "reference": "Patient/patient-example",
    "display": "王小明"
  },
  "effectiveDateTime": "2026-09-03T09:30:00+08:00",
  "valueQuantity": {
    "value": 37.2,
    "unit": "°C",
    "system": "http://unitsofmeasure.org",
    "code": "Cel"
  }
}

可以找出:

  1. status使用code。
  2. subject使用Reference。
  3. effectiveDateTime使用dateTime。
  4. valueQuantity使用Quantity。
  5. Quantity中的value是decimal。
  6. unit提供人類閱讀的單位。
  7. systemcode提供標準化的單位資訊。

從這個例子可以看出,一筆看似簡單的「體溫37.2°C」,其實需要多種資料型別共同表達。


今日小結

今天認識了FHIR的常見資料型別。

基本型別通常表示單一值,例如boolean、integer、decimal、string、code、uri、date及dateTime。

複合型別則由多個欄位組成,例如Identifier、HumanName、Address、ContactPoint、Coding、CodeableConcept、Quantity、Period及Reference。

我認為今天最重要的觀念是:

FHIR資料型別不只是規定資料看起來像什麼,也在規定資料的結構及意義。

即使兩個值在JSON中都是String,在FHIR中也可能分別是date、code或uri,並受到不同規則限制。

下一篇會從今天最後介紹的Reference繼續,看看Patient、Encounter、Observation等不同Resource如何互相連結。

明日預告

Day 11|FHIR Resource如何互相連結?

參考資料

  1. HL7 FHIR R4:Data Types
    https://hl7.org/fhir/R4/datatypes.html

  2. HL7 FHIR R4:References
    https://hl7.org/fhir/R4/references.html

  3. HL7 FHIR R4:Patient Resource
    https://hl7.org/fhir/R4/patient.html

  4. HL7 FHIR R4:Observation Resource
    https://hl7.org/fhir/R4/observation.html

  5. HL7 FHIR R4:UCUM Units
    https://hl7.org/fhir/R4/valueset-ucum-units.html


上一篇
Day 9|FHIR資料為什麼使用JSON?
下一篇
Day 11|FHIR Resource如何互相連結?
系列文
《醫資生的 FHIR 30日入門:用 Postman 讀懂醫療資料交換》30
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言